//
//  CLBaseRequest.h
//  Charles
//
//  Created by Charles on 2018/6/6.
//  Copyright © 2018年 charles. All rights reserved.
//

#import <Foundation/Foundation.h>

// 请求方法类型
typedef NS_ENUM(NSInteger, CLRequestMethodType) {
    CLRequestMethodTypeGET = 0,
    CLRequestMethodTypePOST,
    CLRequestMethodTypeHEAD,
    CLRequestMethodTypePUT,
    CLRequestMethodTypeDELETE,
    CLRequestMethodTypePATCH,
};

typedef NS_ENUM(NSInteger, CLRequestSerializerType) {
    CLRequestSerializerTypeHTTP = 0,
    CLRequestSerializerTypeJSON,
};

typedef NS_ENUM(NSInteger, CLResponseSerializerType) {
    CLResponseSerializerTypeHTTP,
    CLResponseSerializerTypeJSON,
    CLResponseSerializerTypeXMLParser,
};

typedef NS_ENUM(NSInteger, CLRequestPriority) {
    CLRequestPriorityLow = -4L,
    CLRequestPriorityDefault = 0,
    CLRequestPriorityHigh = 4,
};


#pragma mark - 请求相关回调

@protocol AFMultipartFormData;

typedef void (^AFConstructingBlock)(id<AFMultipartFormData> formData);
typedef void (^AFURLSessionTaskProgressBlock)(NSProgress *);

@class CLBaseRequest;
// 请求完成Block
typedef void(^CLRequestCompletionBlock)(__kindof CLBaseRequest *request);

// 请求结束的协议
@protocol CLRequestDelegate <NSObject>

- (void)requestFinished:(__kindof CLBaseRequest *)request;
- (void)requestFailed:(__kindof CLBaseRequest *)request;

@end

// 请求状态流转
@protocol CLRequestAccessory <NSObject>

@end

/**
 所有请求类的基类。持有NSURLSessionTask实例，responseData，responseObject，error等重要数据，
 提供一些需要子类实现的与网络请求相关的方法，处理回调的代理和block，命令YTKNetworkAgent发起网络请求。
 */
@interface CLBaseRequest : NSObject

#pragma mark - 请求和响应的数据信息

@property (nonatomic, strong, readonly) NSURLSessionTask *requestTask;

// 快捷访问 requestTask.currentRequest
@property (nonatomic, strong, readonly) NSURLRequest *currentRequest;
// 快捷访问 requestTask.originalRequest
@property (nonatomic, strong, readonly) NSURLRequest *originalRequest;

@property (nonatomic, strong, readonly) NSHTTPURLResponse *response;

@property (nonatomic, readonly) NSInteger responseStatusCode;

@property (nonatomic, strong, readonly, nullable) NSDictionary *responseHeaders;

@property (nonatomic, strong, readonly, nullable) NSData *responseData;

@property (nonatomic, strong, readonly, nullable) NSString *responseString;

@property (nonatomic, strong, readonly, nullable) id responseObject;

@property (nonatomic, strong, readonly, nullable) id responseJSONObject;

@property (nonatomic, strong, readonly, nullable) NSError *error;

@property (nonatomic, readonly, getter=isCancelled) BOOL cancelled;

@property (nonatomic, readonly, getter=isExecuting) BOOL executing;

#pragma mark - 请求配置

@property (nonatomic) NSInteger tag;

@property (nonatomic, strong, nullable) NSDictionary *userInfo;

@property (nonatomic, weak, nullable) id<CLRequestDelegate> delegate;

@property (nonatomic, copy, nullable) CLRequestCompletionBlock successCompletionBlock;

@property (nonatomic, copy, nullable) CLRequestCompletionBlock failureCompletionBlock;

@property (nonatomic, strong, nullable) NSMutableArray<id<CLRequestAccessory>> *requestAccessories;

@property (nonatomic, copy, nullable) AFConstructingBlock constructingBodyBlock;

@property (nonatomic, strong, nullable) NSString *resumableDownloadPath;

@property (nonatomic, copy, nullable) AFURLSessionTaskProgressBlock resumableDownloadProgressBlock;

@property (nonatomic) CLRequestPriority requestPriority;

// 设置完成回调
- (void)setCompletionBlockWithSuccess:(CLRequestCompletionBlock)success
                              failure:(CLRequestCompletionBlock)failure;
- (void)clearCompletionBlock;

- (void)addAccessory:(id<CLRequestAccessory>)accessory;

#pragma mark - 请求行为

- (void)start;

- (void)stop;

- (void)startWithCompletionBlockWithSuccess:(nullable CLRequestCompletionBlock)success
                                    failure:(nullable CLRequestCompletionBlock)failure;

#pragma mark - 子类重写的方法

- (void)requestCompletePreprocessor;

- (void)requestCompleteFilter;

- (void)requestFailedPreprocessor;

- (void)requestFailedFilter;

- (NSString *)baseUrl;

- (NSString *)requestUrl;

- (NSString *)cdnUrl;

- (NSTimeInterval) requestTimeoutInterval;

- (nullable id)requestArguments;

- (id)cacheFileNameFilterForRequestArgument:(id)argument;

- (CLRequestMethodType)requestMethod;

- (CLRequestSerializerType)requestSerializerType;

- (CLResponseSerializerType)responseSerializerType;

- (nullable NSArray<NSString *> *)requestAuthorizationHeaderFieldArray;

- (nullable NSDictionary<NSString *, NSString *> *)requestHeaderFieldValueDictionary;

- (nullable NSURLRequest *)buildCustomUrlRequest;

- (BOOL)allowsCellularAccess;

- (nullable id)jsonValidator;

@end
